home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / compress / tar321__.zip / SOURCES.ZIP / STREAMER.C < prev    next >
C/C++ Source or Header  |  1994-12-23  |  21KB  |  717 lines

  1. #ifdef __TURBOC__
  2. #include <dos.h>
  3. #include <errno.h>
  4. #include <string.h>
  5.  
  6. #include "pctimer.h"
  7. #define timer pctimer
  8. #include "qic02.h"
  9.  
  10. /*****************************************************\
  11.  * Quarter-Inch-Cartridge no. 02 standart error list *
  12. \*****************************************************/
  13.  
  14. static char *err[] = {
  15.    "udefined error",
  16.    "Ok",
  17.    "reset in progress",    /* hardware status */
  18.    "end of recorded media",
  19.    "bus parity error",
  20.    "beginning of media",
  21.    "marginal block detected",
  22.    "no data detected",
  23.    "illegal command",
  24.    "timeout expired",    /* software flag */
  25.    "file mark detected",
  26.    "block not located",
  27.    "unrecoverable data error",
  28.    "end of medium",
  29.    "write protected",
  30.    "device fault",
  31.    "cartridge not in place",
  32.    "drive busy",    /* software error codes */
  33.    "device not opened",
  34.    "device already opened",
  35. };
  36.  
  37. char **qic02_errlist = err+1;
  38. int  qic02_nerr = sizeof(err)/sizeof(*err) - 1;
  39.  
  40. /****************************************************\
  41.  * Quarter-Inch-Cartridge no. 02 standart interface *
  42. \****************************************************/
  43.  
  44. extern unsigned long timer(void);
  45. extern unsigned long suspend_value(unsigned);
  46. extern void suspend(unsigned long);
  47. extern void interrupt cthandle();
  48. extern long ptr2abs(void far *);
  49.  
  50. static unsigned long wait03us, wait25ms;
  51.  
  52. #define CT_OPENED  0x08
  53. #define CT_CHECKED 0x10
  54. #define CT_EVENT   0x20
  55. #define CT_PROTECT 0x40
  56.  
  57. #define MASK_BOARD 0x7f
  58. #define SKIP_RESET 0x80
  59.  
  60. /* Calculate number of ticks by 300 ms units */
  61. #define TIMEOUT(x) (int)((3*119318L*(x) + 65535L) / 65536L)
  62. #define MINTIME    TIMEOUT(1)
  63. #define MAXTIME    TIMEOUT(1000)
  64. #define WAITIME    TIMEOUT(10)
  65. #define HALT_CPU   /*__emit__(0xf4)*/
  66. #define dim(x)     (sizeof(x)/sizeof(*(x)))
  67. #define NTRY       3
  68.  
  69. #define Q2_READBIT 0x80
  70. #define DMA_WRDEV  8
  71. #define DMA_RDDEV  4
  72.  
  73. static struct _ct_define {
  74.    char ct_name[8];
  75.    WORD valid_base, off_control, off_data, off_launch, off_clear;
  76.    BYTE mask_reset, val_reset;
  77.    BYTE mask_event, not_event;
  78.    BYTE mask_ready, not_ready;
  79.    BYTE mask_excep, not_excep;
  80.    BYTE mask_dma,   done_dma;
  81.    BYTE mask_xfer,  no_xfer;
  82.  
  83.    BYTE set_reset, set_request, set_online;
  84.    BYTE ienable, denable, dma_valid, rundma[8];
  85. } *ct_current = (struct _ct_define *)0;
  86.  
  87. static struct _ct_define sc499 = {
  88.    "archive",
  89.    0x3f8, 1, 0, 2, 3,
  90.    0xf0, 0x50,
  91.    0x80, 0x80,
  92.    0x40, 0x40,
  93.    0x20, 0x20,
  94.    0x10, 0x10,
  95.    0x08, 0x00,
  96.  
  97.    0x80, 0x40, 0,
  98.    0x20, 0x10, 0x0A, { 0, 0, 0, 0, 0, 0, 0, 0 },
  99. };
  100.  
  101. static struct _ct_define sc409a = {
  102.    "everex",
  103.    0x3ff, 0, 1, UNUSED, UNUSED,
  104.    7,    5,
  105.    0,    0,
  106.    1,    1,
  107.    2,    2,
  108.    0,    0,
  109.    4,    4,
  110.  
  111.    2, 4, 1,
  112.    0x40, 0, 0x0E, { 0, 8, 8, 8, 0, 0, 0, 0 },
  113. };
  114.  
  115. static struct _ct_define wangtek = {
  116.    "wangtek",
  117.    0x3ff, 0, 1, UNUSED, UNUSED,
  118.    7,    5,
  119.    0,    0,
  120.    1,    1,
  121.    2,    2,
  122.    0,    0,
  123.    4,    4,
  124.  
  125.    2, 4, 1,
  126.    0, 0, 0x0E, { 0, 8, 8, 16, 0, 0, 0, 0 },
  127. };
  128.  
  129. static struct _ct_define *ct_list[] = {
  130.    &sc499, &sc409a, &wangtek
  131. };
  132.  
  133. struct _ct_pic {
  134.    WORD base;
  135.    BYTE ack, chain;
  136.    void interrupt (*old)();
  137.    int number; BYTE save;
  138. } ct_pic;
  139.  
  140. struct _ct_dma {
  141.    WORD page, address, counter;
  142.    WORD mask, mode, clear;
  143.    BYTE read, write;
  144. } ct_dma;
  145.  
  146. BYTE lastcmd = UNUSED;
  147. WORD ct_error;
  148. volatile struct _ct_psw {
  149.    BYTE flags;
  150.    BYTE input;
  151. } ct_psw;
  152.  
  153. struct _ct_control {
  154.    WORD control, data, launch, clear;
  155.    BYTE mask_reset, val_reset;
  156.    BYTE mask_event, not_event;
  157.    BYTE mask_ready, not_ready;
  158.    BYTE mask_excep, not_excep;
  159.    BYTE mask_state, inv_state;
  160.    BYTE mask_xfer,  no_xfer;
  161.    BYTE mask_dma,   done_dma;
  162.  
  163.    BYTE do_reset, request, online;
  164.    BYTE int_enable, done_enable, dma_enable;
  165. } ct_set;
  166.  
  167. static WORD ct_error;
  168. static BYTE statbuf[6];
  169.  
  170. #define ctlport    (ct_set.control)
  171. #define cmdport    (ct_set.data)
  172. #define statport   (ct_set.control)
  173. #define dataport   (ct_set.data)
  174.  
  175. #define DMAGO      (ct_set.launch)
  176. #define DMACL      (ct_set.clear)
  177.  
  178. #define MASK_RESET ct_set.mask_reset
  179. #define VAL_RESET  ct_set.val_reset
  180. #define MASK_READY ct_set.mask_ready
  181. #define NOT_READY  ct_set.not_ready
  182. #define MASK_EXCEP ct_set.mask_excep
  183. #define NOT_EXCEP  ct_set.not_excep
  184. #define MASK_STATE ct_set.mask_state
  185. #define INV_STATE  ct_set.inv_state
  186. #define DIRC       ct_set.mask_xfer
  187. #define XOFF       ct_set.no_xfer
  188. #define ON         ct_set.online
  189. #define REQ        ct_set.request
  190. #define RESET      ct_set.do_reset
  191. #define EI         ct_set.int_enable
  192. #define ED         ct_set.done_enable
  193. #define DMA        ct_set.dma_enable
  194. #define INP        ct_psw.input
  195. #define DMA_MAIN   ct_dma.mask
  196.  
  197. #define WAIT_READY(t)\
  198.     for ((t)=timer(); ((INP=inportb(statport))&MASK_READY)==NOT_READY;)\
  199.         { if (timer()-(t) > MINTIME) goto error; }
  200. #define WAIT_BUSY(t)\
  201.     for ((t)=timer(); ((INP=inportb(statport))&MASK_READY)!=NOT_READY;)\
  202.         { if (timer()-(t) > MINTIME) goto error; }
  203.  
  204. static int ct_iobyte(int c, unsigned char *p, unsigned length, unsigned tout)
  205. {
  206.    register i;
  207.    register long t, t0;
  208. #if 0
  209.    /* read-only now */ if (!(c & Q2_READBIT)) goto error;
  210. #endif
  211.    ct_psw.flags &= ~CT_CHECKED;
  212.    outportb(cmdport, lastcmd=c);
  213.    outportb(ctlport, REQ);
  214.    WAIT_READY(t);
  215.    outportb(ctlport, ON); /* Clear request */
  216.    WAIT_BUSY(t);
  217.  
  218.    t0 = timer();
  219.    i = c & Q2_READBIT ? XOFF : XOFF^DIRC;
  220.    while (((INP=inportb(statport)) & DIRC) == i) {
  221.       if (timer()-t0 > tout) goto error;
  222.    }
  223.    for (i=0; i<length; i++) {
  224.       WAIT_READY(t);
  225.       if (c & Q2_READBIT) {
  226.          p[i] = inportb(dataport);
  227.       } else {
  228.          outportb(dataport, p[i]);
  229.       }
  230.       outportb(ctlport, REQ);
  231.       suspend(wait03us);
  232.       WAIT_BUSY(t);
  233.       outportb(ctlport, ON);
  234.    }
  235.    return i;
  236. error:
  237.    ct_error = Q2E_DEAD;
  238.    ct_psw.flags |= CT_CHECKED;
  239.    errno = EFAULT;
  240.    return -1;
  241. }
  242.  
  243. static int ct_test(void)
  244. {
  245.    register n;
  246.    register long t;
  247.  
  248.    for (t=timer(); ((INP=inportb(statport))&MASK_STATE)==INV_STATE;) {
  249.       if (timer()-t > MINTIME) {
  250.          ct_error = Q2E_BUSY; goto end;
  251.       }
  252.       HALT_CPU;
  253.    }
  254.    for (n=NTRY; n; n--) {
  255.       if (ct_iobyte(Q2_RDSTAT, statbuf, 6, TIMEOUT(10)) == 6) {
  256.          ct_error = (statbuf[0] & Q2_ERRFLAG) ?
  257.             (statbuf[0] & Q2_ERRMASK) << 8 : 0;
  258.          if (statbuf[1] & Q2_ERRFLAG) ct_error |= statbuf[1] & Q2_ERRMASK;
  259.          break;
  260.       }
  261.    }
  262. end:
  263.    ct_psw.flags |= CT_CHECKED;
  264.    return ct_error;
  265. }
  266.  
  267. static int ct_wait(BYTE mask, BYTE val, unsigned long t0, unsigned tout)
  268. {
  269.    while (((INP=inportb(statport)) & mask) == val) {
  270.       if ((INP & MASK_EXCEP) != NOT_EXCEP) return ct_test();
  271.       if (timer()-t0 > tout) {
  272.          ct_psw.flags |= CT_CHECKED;
  273.          return ct_error = (INP&MASK_READY)==NOT_READY ? Q2E_BUSY : Q2E_DEAD;
  274.       }
  275.       HALT_CPU;
  276.    }
  277.    return 0;
  278. }
  279.  
  280. static int ct_reset(void)
  281. {
  282.    register long t;
  283.  
  284.    outportb(ctlport, ct_set.do_reset);
  285.    suspend(wait25ms);
  286.    outportb(DMACL != UNUSED ? DMACL : ctlport, ON);
  287.    t = timer();
  288.    while ((((INP=inportb(statport)) & MASK_RESET) != VAL_RESET)) {
  289.       if (timer()-t > MINTIME) goto error; HALT_CPU;
  290.    }
  291.    while (!(ct_test() & Q2E_POR)) {
  292.       if (timer()-t > MAXTIME) goto error; HALT_CPU;
  293.    }
  294.    while (ct_test() & Q2E_POR) {
  295.       if (timer()-t > MAXTIME) goto error; HALT_CPU;
  296.    }
  297.    while ((INP=inportb(statport) & MASK_STATE) == INV_STATE) {
  298.       if (timer()-t > MAXTIME) goto error; HALT_CPU;
  299.    }
  300.    return 0;
  301. error:
  302.    return -1;
  303. }
  304.  
  305. int ct_errbit(register unsigned m)
  306. {
  307.    register n = 0;
  308.  
  309.    if (m) {
  310.       if      (m & Q2E_DEAD) m &= Q2E_DEAD;
  311.       else if (m & Q2E_HARD) m &= Q2E_HARD;
  312.       for (n=16; n && !(m & 0x8000); --n, m<<=1);
  313.    }
  314.    return n;
  315. }
  316.  
  317. static void ct_end(void)
  318. {
  319.    if (!(ct_psw.flags & CT_OPENED)) {
  320.       errno = EFAULT;
  321.    } else {
  322.       if (ct_pic.base != UNUSED) {
  323.          setvect(ct_pic.number, ct_pic.old);
  324.          if (ct_pic.save & (1 << (ct_pic.ack & 7)))
  325.             outportb(ct_pic.base+1, ct_pic.save);
  326.       }
  327.       ct_psw.flags = 0;
  328.    }
  329. }
  330.  
  331. static void ct_pause(void)
  332. {
  333.    register long t; for (t=timer(); timer()-t <= MINTIME;) HALT_CPU;
  334. }
  335.  
  336. static int ct_begin(register struct init_data *d, int board_type)
  337. {
  338.    register WORD i;
  339.    static BYTE page_tab[] = {0x87,0x83,0x81,0x82,0x8f,0x8b,0x89,0x8A};
  340.    static BYTE addr_tab[] = { 0,   2,   4,   6,  0xC0,0xC4,0xC8,0xCC};
  341.    static BYTE cntr_tab[] = { 1,   3,   5,   7,  0xC2,0xC6,0xCA,0xCE};
  342.    register j; register long t;
  343.  
  344.    if ((i = board_type & MASK_BOARD) >= dim(ct_list)) {
  345.       errno = ENODEV; return CTE_FAULT;
  346.    } else {
  347.       ct_current = ct_list[i];
  348.    }
  349.    i = d->base_address;
  350.    if (i & ~(ct_current->valid_base)) {
  351.       errno = EINVDAT; return CTE_FAULT;
  352.    } else {
  353.       ct_set.control = i + ct_current->off_control;
  354.       ct_set.data    = i + ct_current->off_data;
  355.       DMAGO  = ct_current->off_launch == UNUSED ?
  356.                UNUSED : i + ct_current->off_launch;
  357.       DMACL  = ct_current->off_clear  == UNUSED ?
  358.                UNUSED : i + ct_current->off_clear;
  359.  
  360.       ct_set.mask_reset = ct_current->mask_reset;
  361.       ct_set.val_reset  = ct_current->val_reset;
  362.       ct_set.mask_event = ct_current->mask_event;
  363.       ct_set.not_event  = ct_current->not_event;
  364.       ct_set.mask_ready = ct_current->mask_ready;
  365.       ct_set.not_ready  = ct_current->not_ready;
  366.       ct_set.mask_excep = ct_current->mask_excep;
  367.       ct_set.not_excep  = ct_current->not_excep;
  368.       ct_set.mask_state = ct_set.mask_ready | ct_set.mask_excep;
  369.       ct_set.inv_state  = ct_set.not_ready  | ct_set.not_excep;
  370.       ct_set.mask_xfer  = ct_current->mask_xfer;
  371.       ct_set.no_xfer    = ct_current->no_xfer;
  372.       ct_set.mask_dma   = ct_current->mask_dma;
  373.       ct_set.done_dma   = ct_current->done_dma;
  374.  
  375.       ct_set.online   = ct_current->set_online;
  376.       ct_set.request  = ct_current->set_request | ct_set.online;
  377.       ct_set.do_reset = ct_current->set_reset;
  378.    }
  379.    i = d->dma_number;
  380.    if (i == UNUSED) {
  381.       ct_dma.page = ct_dma.address = ct_dma.counter = UNUSED;
  382.       ct_dma.mask = ct_dma.mode    = ct_dma.clear   = UNUSED;
  383.       ct_set.dma_enable = 0;
  384.    } else if (i & ~7 || !((ct_current->dma_valid >> i) & 1)) {
  385.       errno = EINVDAT; return CTE_FAULT;
  386.    } else {
  387.       ct_set.dma_enable = ct_current->rundma[i];
  388.       ct_dma.page    = page_tab[i];
  389.       ct_dma.address = addr_tab[i];
  390.       ct_dma.counter = cntr_tab[i];
  391.       if (i & ~3) {/* slave device */
  392.          ct_dma.mask  = 0xd4;
  393.          ct_dma.mode  = 0xd6;
  394.          ct_dma.clear = 0xd8;
  395.       } else {/* primary device */
  396.          ct_dma.mask  = 0xA;
  397.          ct_dma.mode  = 0xB;
  398.          ct_dma.clear = 0xC;
  399.       }
  400.       i &= 3;
  401.       /* single mode, address increment, no auto-init */
  402.       ct_dma.write = 0x40 | DMA_WRDEV | i;
  403.       ct_dma.read  = 0x40 | DMA_RDDEV | i;
  404.    }
  405.    i = d->irq_number;
  406.    if (i == UNUSED) {
  407.       ct_pic.number = ct_pic.base = UNUSED;
  408.       ct_set.int_enable = ct_set.done_enable = 0;
  409.    } else if (i & ~15) {
  410.       errno = EINVDAT; return CTE_FAULT;
  411.    } else {
  412.       ct_set.int_enable  = ct_current->ienable;
  413.       ct_set.done_enable = ct_current->denable ?
  414.                            ct_current->denable : ct_current->ienable;
  415.  
  416.       if (i & ~7) {/* slave controller */
  417.          ct_pic.number = i + 0x68;
  418.          ct_pic.base   = 0xA0;
  419.       } else {/* primary controller */
  420.          ct_pic.number = i + 8;
  421.          ct_pic.base   = 0x20;
  422.       }
  423.       i &= 7;
  424.       ct_pic.old   = getvect(ct_pic.number);
  425.       ct_pic.ack   = 0x60 | i; /* specific EOI */
  426.       ct_pic.save  = inportb(ct_pic.base + 1);
  427.       ct_pic.chain = ct_pic.old && ~(ct_pic.save >> i) & 1;
  428.    }
  429.    wait03us = suspend_value(3);
  430.    wait25ms = suspend_value(25000);
  431.  
  432.    if ((board_type & SKIP_RESET) == 0) {
  433.       if (ct_reset()) return (errno = EFAULT, CTE_DEAD);
  434.    }
  435.    if (ct_pic.base != UNUSED) {
  436.       setvect(ct_pic.number, cthandle);
  437.       if ((i = 1 << (ct_pic.ack & 7)) & ct_pic.save)
  438.          outportb(ct_pic.base+1, ~i & ct_pic.save);
  439.    }
  440.    ct_error = 0; ct_psw.flags |= CT_OPENED;
  441.    for (t=timer(), j=0;;) {
  442.       i = ct_test();
  443.       if (i & Q2E_WRP) ct_psw.flags |= CT_PROTECT;
  444.       if (!(i & ~(Q2E_BOM|Q2E_FIL|Q2E_WRP))) return 0;
  445.       if (timer()-t > MAXTIME) break;
  446.       if (!(i & Q2E_POR) && ++j >= NTRY) break;
  447.       ct_pause();
  448.    }
  449.    ct_end(); errno = EFAULT; return ct_errbit(i);
  450. }
  451.  
  452. static int ct_issue(int c)
  453. {
  454.    register unsigned long tick;
  455.  
  456.    if (ct_wait(MASK_STATE,INV_STATE,timer(),MINTIME) & Q2E_STOP) goto end;
  457.  
  458.    ct_psw.flags &= ~CT_CHECKED;
  459.    outportb(cmdport, lastcmd=c);
  460.    outportb(ctlport, REQ);
  461.    if (ct_wait(MASK_READY,NOT_READY,timer(),MINTIME) & Q2E_HARD) goto end;
  462.    ct_psw.flags &= ~CT_EVENT;
  463.    INP = (INP & ~ct_set.mask_event) | ct_set.not_event;
  464.    outportb(ctlport, ON|EI); /* Clear request, interrupt enable */
  465.    WAIT_BUSY(tick);
  466.    return 0;
  467. error:
  468.    ct_error = Q2E_DEAD;
  469.    ct_psw.flags |= CT_CHECKED;
  470. end:
  471.    return ct_errbit(ct_error);
  472. }
  473.  
  474. static int ct_complete(void)
  475. {
  476.    register long t;
  477.    for (t=timer();;) {
  478.       if (((INP=inportb(statport)) & MASK_STATE)!=INV_STATE) break;
  479.       if (timer()-t > MAXTIME) return (ct_error = Q2E_DEAD, CTE_DEAD);
  480.       HALT_CPU;
  481.    }
  482.    return 0;
  483. }
  484.  
  485. static int ct_iodma(int c, void *buf, unsigned length)
  486. {
  487.    register unsigned k;
  488.    register unsigned inp;
  489.    register long t, t0;
  490.    long address;
  491.  
  492.    address = ptr2abs(buf);
  493.    if (DMA_MAIN & 0xf0) {
  494.       /* Secondary DMA requires word alignment */
  495.       if (address & 1 || length & 1) return (errno = EINVMEM, CTE_FAULT);
  496.       address >>= 1;
  497.       length  >>= 1;
  498.    }
  499.    length -= 1;
  500.    /* Check for writing across DMA page */
  501.    if (((address+length) ^ address) & ~0xffffL)
  502.       return (errno = EINVMEM, CTE_FAULT);
  503.  
  504.    t0 = timer();
  505.    if (lastcmd!=c) {
  506.       if (DMACL != UNUSED) outportb(DMACL, 0);
  507.       /********** Issue a command **********/
  508.       outportb(cmdport, lastcmd=c);
  509.       outportb(ctlport, REQ);
  510.       if (ct_wait(MASK_READY, NOT_READY,
  511.                  (c & Q2_READBIT ? timer() : t0),
  512.                  (c & Q2_READBIT ? MINTIME : MAXTIME)) & Q2E_HARD)
  513.          goto error;
  514.       outportb(ctlport, ON|ED|DMA);
  515.       WAIT_BUSY(t);
  516.    }
  517.    /* Clear status */
  518.    ct_psw.flags &= ~(CT_EVENT|CT_CHECKED);
  519.    INP = (INP & ~ct_set.mask_event) | ct_set.not_event;
  520.  
  521.    /********** Initialise DMA **********/
  522.    outportb(ct_dma.mask, 4|(ct_dma.read & 3));
  523.    outportb(ct_dma.mode, c & Q2_READBIT ? ct_dma.read : ct_dma.write);
  524.    outportb(ct_dma.page, (WORD)(address >> 16));
  525.  
  526.    if (DMA_MAIN & 0xf0) {/* secondary controller */
  527.       outport(ct_dma.address, (WORD)address);
  528.       outport(ct_dma.counter, length);
  529.    } else {
  530.       disable();
  531.       outportb(ct_dma.clear,   0);
  532.       outportb(ct_dma.address, (WORD)address);
  533.       outportb(ct_dma.address, (WORD)address>>8);
  534.       outportb(ct_dma.counter, length);
  535.       outportb(ct_dma.counter, length>>8);
  536.       enable();
  537.    }
  538.    if (c & Q2_READBIT) {
  539.       if (ct_wait(DIRC,XOFF,t0,MAXTIME) & Q2E_HARD) goto error;
  540.    }
  541.    if (DMAGO != UNUSED) outportb(DMAGO, 0);
  542.    outportb(ct_dma.mask, (ct_dma.read & 3));
  543.  
  544.    /* Wait for the end of operation */
  545.    for (;;) {
  546.       INP = inp = inportb(statport);
  547.       if ((INP & MASK_EXCEP) != NOT_EXCEP) {
  548.          if (ct_test() & Q2E_HARD) goto error;
  549.          break;
  550.       }
  551.       if (ct_set.mask_dma) {
  552.          if ((INP & ct_set.mask_dma) == ct_set.done_dma) break;
  553.       } else {
  554.          if ((INP & MASK_READY) != NOT_READY) break;
  555.       }
  556.       if (timer()-t0 > MAXTIME) goto error;
  557.       HALT_CPU;
  558.    }
  559.    /********** Get number of bytes transferred **********/
  560.    if (DMA_MAIN & 0xf0) {/* secondary controller */
  561.       k = inport(ct_dma.counter);
  562.       k = (length - k) << 1;
  563.    } else {
  564.       disable();
  565.       outportb(ct_dma.clear, 0);
  566.       k  = inportb(ct_dma.counter);
  567.       k |= inportb(ct_dma.counter) << 8;
  568.       enable();
  569.       k = length - k;
  570.    }
  571.    if (!(c & Q2_READBIT) &&
  572.       (inp & MASK_READY) == NOT_READY && (INP & MASK_READY) == NOT_READY) {
  573.       (void)ct_wait(MASK_READY,NOT_READY,t0,MAXTIME);
  574.    }
  575.    return k;
  576.  
  577.    /********** Error occured **********/
  578. error:
  579.    if (DMACL != UNUSED) outportb(DMACL, 0);
  580.    return (errno = EFAULT, CTE_FAULT);
  581. }
  582.  
  583. static int ct_inout(int c, void *buf, unsigned length)
  584. {
  585.    if (ct_wait(MASK_READY,NOT_READY,timer(),
  586.               (c & Q2_READBIT ? MAXTIME : WAITIME)) & Q2E_STOP)
  587.       return -1;
  588.    return DMA_MAIN == UNUSED ?
  589.              ct_iobyte(c, buf, length, MAXTIME) :
  590.              ct_iodma(c, buf, length);
  591. }
  592.  
  593. int streamer(register int op, void *ptr, int arg)
  594. {
  595.    register i;
  596.    register long t;
  597.  
  598.    op |= 'z'^'Z';
  599.    if (op == '?') {
  600.       for (op=dim(ct_list); --op >= 0;) {
  601.          if (stricmp(ct_list[op]->ct_name, ptr) == 0) goto end;
  602.       }
  603.       goto end;
  604.    } else if (op == 'o') {/* open device */
  605.       op = ct_psw.flags & CT_OPENED ?
  606.          (errno=EFAULT, CTE_OPENED) :
  607.          ct_begin((struct init_data *)ptr, arg);
  608.       goto end;
  609.    }
  610.    if (!(ct_psw.flags & CT_OPENED)) return (errno=EFAULT, CTE_CLOSED);
  611.    switch (op) {
  612.       case 'c': /* end - close device */
  613.          ct_end();
  614.          op = 0;
  615.          break;
  616.       case 't': /* read status */
  617.          op = ct_errbit(ct_psw.flags&CT_CHECKED ? ct_error : ct_test());
  618.          if (ptr) {
  619.             ((struct qic02_word_status *)ptr)->status = ct_error;
  620.             ((struct qic02_word_status *)ptr)->error_cnt =
  621.                (statbuf[2] << 8) | statbuf[3];
  622.             ((struct qic02_word_status *)ptr)->underrun_cnt =
  623.                (statbuf[4] << 8) | statbuf[5];
  624.          }
  625.          ct_psw.flags &= ~CT_CHECKED;
  626.          break;
  627.       case 'd': /* "drop online" - write FM and rewind */
  628.          if (ct_current == &wangtek) {
  629.            if (ct_wait(MASK_STATE,INV_STATE,timer(),MINTIME) & Q2E_STOP) {
  630.               op = ct_errbit(ct_error); break;
  631.            }
  632.            ct_psw.flags &= ~CT_CHECKED;
  633.            lastcmd = 0; /* dummy */
  634.            outportb(ctlport, 0); /* drop online */
  635.  
  636.             for (t=timer(); timer()-t <= MAXTIME;) {
  637.                if (((INP=inportb(statport))&MASK_STATE)!=INV_STATE) break;
  638.                HALT_CPU;
  639.             }
  640.             ct_test();
  641.             if (ct_error & Q2E_HARD) goto test_rewind;
  642.             if (ct_error & Q2E_BOM) { op = 0; break; }
  643.          } else if (!(ct_psw.flags & CT_PROTECT)) {
  644.             /* write file mark */
  645.             if (ct_issue(Q2_WRMARK)!=0 || ct_complete()!=0) {
  646.                ct_test(); op = -1; break;
  647.             }
  648.          }
  649.       case 'n': /* rewind */
  650.      for (op=0, i=0;;) {
  651.             if (ct_issue(Q2_REWIND) == 0) {
  652.                for (t=timer(); timer()-t <= MAXTIME;) {
  653.                   if (((INP=inportb(statport))&MASK_STATE)!=INV_STATE) break;
  654.                   HALT_CPU;
  655.            }
  656.            ct_test();
  657.            if (ct_error & Q2E_HARD) break;
  658.            if (ct_error & Q2E_BOM) goto end;
  659.         }
  660.         if (++i >= NTRY) break;
  661.         if (ct_reset()) {
  662.                ct_error = Q2E_DEAD; break;
  663.         }
  664.      }
  665.       test_rewind:
  666.      op = ct_error & ~Q2E_WRP;
  667.      op = op ? ct_errbit(op) : CTE_FAULT;
  668.          break;
  669.       case 'i': /* issue a command */
  670.          arg &= 255;
  671.          if (arg == Q2_RDDATA || arg == Q2_WRDATA || arg == Q2_RDSTAT) {
  672.             errno = EINVAL; op = CTE_FAULT;
  673.          } else {
  674.             ct_psw.flags &= ~CT_CHECKED;
  675.             if ((op = ct_issue(arg)) == 0) op = ct_complete();
  676.          }
  677.          break;
  678.       case 'f': /* forward space file(s) */
  679.          for (op=0; op<arg; op++) {
  680.             ct_issue(Q2_RDMARK); if (ct_complete() != 0) break;
  681.          }
  682.          if (op != arg) ct_test();
  683.          break;
  684.       case 'r': /* read */
  685.          if ((op = ct_inout(Q2_RDDATA, ptr, arg)) != arg) {
  686.             if (!(ct_psw.flags & CT_CHECKED)) ct_test();
  687.             if (ct_error & Q2E_FIL && !(ct_error & Q2E_HARD)) {
  688.                /* file mark detected */ op = 0;
  689.             }
  690.          }
  691.          break;
  692.       case 'w': /* write */
  693.          if (ct_psw.flags & CT_PROTECT) {
  694.             ct_psw.flags |= CT_CHECKED;
  695.             ct_error = Q2E_WRP;
  696.             op = CTE_FAULT;
  697.             break;
  698.          }
  699.          if (!arg) {
  700.             /* write file mark */
  701.             if (ct_issue(Q2_WRMARK)!=0 || ct_complete()!=0) {
  702.                ct_test();
  703.                op = -1;
  704.             }
  705.          } else {
  706.             op = ct_inout(Q2_WRDATA, ptr, arg);
  707.          }
  708.          break;
  709.       default:
  710.          errno = EINVFNC;
  711.          op = CTE_FAULT;
  712.    }
  713. end:
  714.    return op;
  715. }
  716. #endif
  717.